﻿using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using NetduinoHappyHour.Util;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
using NetduinoHappyHour.Asynchronous;

namespace NetduinoHappyHour.Hardware
{
    /// <summary>
    /// drive command that allows to run left and right wheel independent
    /// Written by: Salvador Richter
    /// Appache License Version 2.0 
    /// </summary>
    public class DriveCommandDualAsync : IDriveCommand
    {
        public DriveCommandLeft Left{get;set;}
        public DriveCommandRight Right{get;set;}

        public int StepDuration { set { Left.StepDuration = value; Right.StepDuration = value; } }
        public int StepDurationLeft { set { Left.StepDuration = value; } }
        public int StepDurationRight { set { Right.StepDuration = value; } }
        public bool IsDirectionForwardLeft { set { Left.IsDirectionForward = value; } }
        public bool IsDirectionForwardRight { set { Right.IsDirectionForward = value; } }
        public bool IsValid { set { Left.IsValid = value; Right.IsValid = value; } }
        public bool IsPaused { set { Left.IsPaused = value; Right.IsPaused = value; } }
        public bool IsEndlessRunning { set { Left.IsEndlessRunning = value; Right.IsEndlessRunning = value; } }

        /// <summary>Creates a DriveCommand, with step duration only --> will create endless running DriveCommand</summary>
        ///
        /// <param name="stepDuration">step duration for both wheels, if zero default speed is used</param>
        public DriveCommandDualAsync(string StepDuration) : this(int.Parse(StepDuration))
        {
        }

        /// <summary>Creates a DriveCommand, with step duration only --> will create endless running DriveCommand</summary>
        ///
        /// <param name="stepDuration">step duration for both wheels, if zero default speed is used</param>
        public DriveCommandDualAsync(int StepDuration)
        {
            Left = new DriveCommandLeft(StepDuration);
            Right = new DriveCommandRight(StepDuration);
        }

        /// <summary>Creates a DriveCommand using param in string representation</summary>
        ///
        /// <param name="stepsL">number of steps to be run by left engine, for movement per step see SystemConfig, on negative Value DirectionForwardL is set to false</param>
        /// <param name="stepsR">number of steps to be run by right engine, for movement per step see SystemConfig, on negative Value DirectionForwardR is set to false</param>
        /// <param name="stepDuration">step duration for both wheels, if zero default speed is used</param>
        public DriveCommandDualAsync(String stepsL, String stepsR, String stepDuration)
            : this(int.Parse(stepsL), int.Parse(stepsR), int.Parse(stepDuration))
        {
        }

        /// <summary>Creates a DriveCommand</summary>
        ///
        /// <param name="stepsL">number of steps to be run by left engine, for movement per step see SystemConfig, on negative Value DirectionForwardL is set to false</param>
        /// <param name="stepsR">number of steps to be run by right engine, for movement per step see SystemConfig, on negative Value DirectionForwardR is set to false</param>
        /// <param name="stepDuration">step duration for both wheels, if zero default speed is used</param>
        public DriveCommandDualAsync(int stepsL, int stepsR, int stepDuration)
        {
            Left = new DriveCommandLeft(stepsL, stepDuration);
            Right = new DriveCommandRight(stepsR, stepDuration);
        }

        /// <summary>
        /// Executes a DriveCommand. Each step if postponed by a wait cycle, so no special handling for engines rotation required
        /// Uses GPIO PIN D10 to D13
        /// </summary>
        /// <param name="dCommand">
        /// The drive command to be executed
        /// </param>
        public void Execute()
        {
            ExecuteAsync execLeft = new ExecuteAsync(Left);
            ExecuteAsync execRight = new ExecuteAsync(Right);
            execLeft.Execute();
            execRight.Execute();
        }
    }
}
